package com.cart.seon.usbconnection.base.service;

import android.media.MediaPlayer;
import android.util.Log;

import com.cart.seon.usbconnection.base.impl.MusicPlayerListener;
import com.cart.seon.usbconnection.base.utils.FileUtils;

public class MusicPlayerService {

    static {
        TAG = MusicPlayerService.class.getName();
        DEFAULT_LISTENER = new MusicPlayerListener() {
            @Override
            public void onPlay() {
                Log.d(TAG, "歌曲开始播放");
            }

            @Override
            public void onPause() {
                Log.d(TAG, "歌曲已暂停");
            }

            @Override
            public void onStop() {
                Log.d(TAG, "歌曲已中断");
            }
        };
    }

    private static volatile MusicPlayerService instance;

    private MusicPlayerListener listener;

    private final MediaPlayer mediaPlayer;

    private static final String TAG;

    private static final MusicPlayerListener DEFAULT_LISTENER;

    private String lastPlayedHash;


    /**
     * 无回调函数获取实例
     *
     * @return 音乐播放基底服务
     */
    public static MusicPlayerService getInstance() {
        return getInstance(null);
    }

    /**
     * 有回调函数获取实例
     * 单例模式，防止后期多个实例随意播放音乐
     *
     * @param listener 回调函数
     * @return 音乐播放基底服务
     */
    public static MusicPlayerService getInstance(MusicPlayerListener listener) {
        if (instance == null) {
            synchronized (MusicPlayerService.class) {
                if (instance == null) {
                    instance = new MusicPlayerService(listener);
                }
            }
        }
        return instance;
    }

    private MusicPlayerService(MusicPlayerListener listener) {
        // 初始化 MediaPlayer
        mediaPlayer = new MediaPlayer();
        // listener为空时提供默认接口实现
        if (listener == null) {
            setListener(DEFAULT_LISTENER);
        } else {
            setListener(listener);
        }
    }

    /**
     * 在某一节点播放歌曲(可在程序末尾执行onPlay回调)
     * 要注意本方法仅仅用于记忆播放初始化，会直接将歌曲指针指向position。
     * 后续如果要继续播放的话要将方法换为playByPath。
     *
     * @param path     歌曲路径
     * @param position 时间节点(毫秒ms)
     */
    public void initMediaSeekOn(String path, int position) {
        lastPlayedHash = FileUtils.calculateFileHash(path);
        initMediaResource(path);
        mediaPlayer.seekTo(position);
        playInternal();
    }

    /**
     * 根据路径进行音乐播放(可在程序末尾执行onPlay回调)
     *
     * @param path 音乐路径（绝对路径）
     */
    public void playByPath(String path) {
        // 对比MD5值，如果是已经在播放的音乐则接着播放
        String currentHash = FileUtils.calculateFileHash(path);
        if (currentHash.equals(lastPlayedHash)) {
            playInternal();
        } else {
            lastPlayedHash = currentHash;
            initMediaResource(path);
            playInternal();
        }
    }

    private void playInternal() {
        mediaPlayer.start();
        notifyPlay();
    }

    private void initMediaResource(String musicFilePath) {
        try {
            mediaPlayer.reset();
            mediaPlayer.setDataSource(musicFilePath);
            mediaPlayer.prepare();
        } catch (Exception e) {
            // todo:后期采用更高级的日志系统，可能会发生文件不存在等情况
            e.printStackTrace();
        }
    }

    /**
     * 暂停歌曲，可在暂停后执行回调(可在程序末尾执行onPause回调)
     */
    public void pause() {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.pause();
            notifyPause();
        }
    }

    /**
     * 停止歌曲, 可在停止后执行回调(可在程序末尾执行onStop回调)
     */
    public void stop() {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
            mediaPlayer.reset();
            lastPlayedHash = null; // 让音乐能够重新被加载
            notifyStop();
        }
    }

    private void setListener(MusicPlayerListener listener) {
        this.listener = listener;
    }

    private void notifyPlay() {
        if (listener != null) {
            listener.onPlay();
        }
    }

    private void notifyPause() {
        if (listener != null) {
            listener.onPause();
        }
    }

    private void notifyStop() {
        if (listener != null) {
            listener.onStop();
        }
    }
}
